// [1] 禁止出现调试器，出现单词eruda就不允许提交
// [2] 监测到公共文件修改，则不允许提交
const tool = require("./node_tool");
const fs = require("fs");
const path = require("path");
class CommitMessage {
  constructor() {
    this.init();
    this.currentPath = path.resolve(__dirname);
  }
  async init() {
    let currentPath = path.resolve(__dirname);
    // 1. 获取分支名
    let branchName = await tool.getBranchName(currentPath);
    // 【规则1】检测本次修改的内容若包含eruda，则不允许提交
    // let modifiedContent = await tool.execute(`git diff HEAD`, currentPath);
    // if (branchName === "pre_master" && modifiedContent.includes("eruda")) {
    //   tool.print("red", "检测到包含调试器代码，不允许提交");
    //   process.exit(1);
    // }
    // 2. 获取公共文件配置
    let serverConfig = await this.httpGet(
      `http://192.168.50.190:8080/pmapi/common/common_config_get.php?config_name=common_files_map`
    );
    let {
      data: {
        detail: {
          // <替换 zl_new_official>
          config: { zl_new_official: commonFilePaths },
        },
      },
    } = serverConfig;
    // 获取本次改动的文件
    let changedFiles = await tool.getChangedFiles(currentPath);
    // 是否改动了公共文件
    let changedCommonFiles = changedFiles.filter((item) => {
      return commonFilePaths.includes(item);
    });
    if (!changedCommonFiles.length) return;
    // 【规则2】检测到改动了公共文件，则上报项目系统
    const eslintVersion = await tool.getEslintVersion(currentPath);
    const npmVersion = await tool.getNpmVersion(currentPath);
    const nodeVersion = await tool.getNodeVersion(currentPath);
    const packerName = await tool.getCurrentPacker(currentPath);
    const packerEmail = await tool.getCurrentPackerEmail(currentPath);
    const prettierVersion = await tool.getPrettierVersion(currentPath);
    let git_repo = await tool.getRepoUrl(currentPath)
    git_repo = git_repo.match(/[^\/]+\.git/g)[0]
    git_repo = git_repo.replace(/\.git/g,'')
    let reportInfo = {
      changed_files: JSON.stringify(changedCommonFiles),
      // <替换 zl_new_official>
      platform: "zl_new_official",
      branch: branchName,
      // <替换 之了新官网>
      project_name: '之了新官网',
      eslint_version: eslintVersion,
      npm_version: npmVersion,
      node_version: nodeVersion,
      packer_name: packerName,
      packer_email: packerEmail,
      prettier_version: prettierVersion,
      folder_path: process.cwd(),
      git_repo: git_repo
    };
    await this.httpPost(
      `http://192.168.50.190:8080/pmapi/common_files_monitor/report.php`,
      reportInfo
    );
    return 1
  }
  qsStringify(obj) {
    const result = [];
    const getType = function (o) {
      return Object.prototype.toString
        .call(o)
        .toLowerCase()
        .replace(/[\[\]]/g, "")
        .split(" ")[1];
    };
    if (getType(obj) !== "object") {
      return "";
    }
    // 遍历数组或对象
    const traverse = function (o, lastKey = "") {
      if (getType(o) === "object") {
        Object.keys(o).forEach((key) => {
          let item = o[key];
          const subType = getType(item);
          if (["object", "array"].includes(subType)) {
            const keyValue = lastKey ? `${lastKey}[${key}]` : `${key}`;
            traverse(item, keyValue);
          } else {
            if (["undefined", "null", "function"].includes(subType)) {
              item = "";
            }
            const keyValue = lastKey
              ? `${lastKey}[${key}]=${encodeURIComponent(item)}`
              : `${key}=${encodeURIComponent(item)}`;
            result.push(keyValue);
          }
        });
      }
      if (getType(o) === "array") {
        o.forEach((item, index) => {
          const subType = getType(item);
          if (["object", "array"].includes(subType)) {
            const keyValue = `${lastKey}[${index}]`;
            traverse(item, keyValue);
          } else {
            if (["undefined", "null", "function"].includes(subType)) {
              item = "";
            }
            const keyValue = `${lastKey}[${index}]=${encodeURIComponent(item)}`;
            result.push(keyValue);
          }
        });
      }
    };
    traverse(obj);
    return result.join("&");
  }
  // 解析查询字符串
  qsParse(queryString) {
    if (typeof queryString !== "string") {
      return {};
    }
    let arr = queryString.match(/[^&=#?]+=[^&=#?]+/g);
    if (arr === null) {
      return {};
    }
    arr = arr.map((item) => {
      return { key: item.split("=")[0], value: item.split("=")[1] };
    });
    // 重新组装数据
    let result = {};
    arr.forEach((item) => {
      let { key, value } = item;
      let allKeys = key.match(/[^\[\]]+/g);
      // 连续创建对象
      if (allKeys.length === 1) {
        // 存在一个key
        result[key] = decodeURIComponent(value);
      } else {
        // 递归创建对象或数组
        let lastValue = result; // 存取上次递归得到的对象或数组
        let len = allKeys.length;
        for (let i = 0; i < len - 1; i++) {
          let current = allKeys[i];
          let next = allKeys[i + 1];
          if (lastValue[current] === undefined) {
            lastValue[current] = isNaN(next) ? {} : [];
            lastValue = lastValue[current];
          }
          if (lastValue[current]) {
            lastValue = lastValue[current];
          }
        }
        let lastKey = allKeys[len - 1];
        lastValue[lastKey] = decodeURIComponent(value);
      }
    });
    return result;
  }
  // 使用request模块发请求
  async httpPost(url, postParams) {
    let fetch = null;
    try {
      fetch = require("node-fetch");
    } catch (e) {
      this.print("red", "请安装node-fetch，执行“cnpm i node-fetch@2.6.6 -D”");
      process.exit(1);
    }

    const bodyStr = this.qsStringify(postParams);
    // console.log(bodyStr)
    const response = await fetch(url, {
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      method: "POST",
      body: bodyStr,
    });
    const data = await response.json();
    return data;
  }

  // 封装get请求
  async httpGet(url, params) {
    let fetch = null;
    try {
      fetch = require("node-fetch");
    } catch (e) {
      this.print("red", "请安装node-fetch，执行“cnpm i node-fetch@2.6.6 -D”");
      process.exit(1);
    }
    let realUrl = url.split("?")[0];
    let query = this.qsParse(url);
    let combineParams = Object.assign({}, query, params);

    const queryString = this.qsStringify(combineParams);
    const response = await fetch(realUrl + "?" + queryString, {
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      method: "GET",
    });
    const data = await response.json();
    return data;
  }
}
new CommitMessage();
